<?php


namespace App\Services;


use App\Repositories\ResponseCode;
use Illuminate\Support\Facades\Redis;
use Jiannei\Response\Laravel\Support\Facades\Response;

class Sign
{


    /**
     * 验证签名
     * @param $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function verifySign($request)
    {
        $params = $request->all();
        if (!isset($params['nonce']) || empty($params['nonce']))
            Response::fail(__('api.DEFECT_NONCE'), ResponseCode::DEFECT_NONCE);
        if (!isset($params['timestamp']) || empty($params['timestamp']))
            Response::fail(__('api.DEFECT_TIMESTAMP'), ResponseCode::DEFECT_TIMESTAMP);
        if (!isset($params['sign']) || empty($params['sign']))
            Response::fail(__('api.DEFECT_SIGN'), ResponseCode::DEFECT_SIGN);
        if (Redis::sismember('signNonce', $params['nonce']))
            Response::fail(__('api.INVALID_NONCE'), ResponseCode::INVALID_NONCE);
        if ($params['timestamp'] < time() - 30 && $params['timestamp'] > time() + 30)
            Response::fail(__('api.INVALID_TIMESTAMP'), ResponseCode::INVALID_TIMESTAMP);
        $sign = self::signCreate($params);
        if ($sign !== $params['sign'])
            Response::fail(__('api.INVALID_SIGN'), ResponseCode::INVALID_SIGN);
        Redis::sadd('signNonce', $params['nonce']);
    }


    /**
     * 生成签名
     * @param $params
     * @return string
     */
    private function signCreate($params)
    {
        unset($params['sign']);
        ksort($params);
        foreach ($params as $key => $value) {
            if (is_array($value)) {
                $params[$key] = implode(',', $value);
            }
        }
        $p = array_merge([
            'sign_start_key' => config('auth.sign_start_key')],
            $params,
            ['sign_end_key' => config('auth.sign_end_key')]
        );
        $strParam = urldecode($this->_http_build_query($p));
//        print_r($strParam);
//        echo '-----------' . strtoupper(md5($strParam));
        return strtoupper(md5($strParam));
    }

    /**
     * 参数拼接
     * @param $data
     * @param null $prefix
     * @param null $sep
     * @param string $key
     * @param bool $urlencode
     * @return string
     */
    private function _http_build_query($data, $prefix = null, $sep = null, $key = '', $urlencode = true)
    {
        $ret = array();

        foreach ((array)$data as $k => $v) {
            if ($urlencode) {
                $k = urlencode($k);
            }
            if (is_int($k) && null != $prefix) {
                $k = $prefix . $k;
            }
            if (!empty($key)) {
                $k = $key . '%5B' . $k . '%5D';
            }

            if (is_array($v) || is_object($v)) {
                array_push($ret, $this->_http_build_query($v, '', $sep, $k, $urlencode));
            } elseif ($urlencode) {
                array_push($ret, $k . '=' . urlencode($v));
            } else {
                array_push($ret, $k . '=' . $v);
            }
        }

        if (null === $sep) {
            $sep = ini_get('arg_separator.output');
        }

        return implode($sep, $ret);
    }

}
